<template>
  <div class="app-container">
    <!-- 测试进度条 -->
    <div class="progress-section">
      <el-progress 
        :percentage="progressPercentage" 
        :stroke-width="8"
        :text-inside="true"
        :format="formatProgress"
      ></el-progress>
      <div class="progress-info">
        <span>第 {{ currentQuestionIndex + 1 }} 题 / 共 {{ totalQuestions }} 题</span>
        <span v-if="timeLimit" class="time-remaining">
          <el-icon><Timer /></el-icon>
          剩余时间：{{ formatTime(timeRemaining) }}
        </span>
      </div>
    </div>

    <!-- 加载状态 -->
    <div v-if="loadingCurrentQuestion" class="loading-section">
      <el-card>
        <div class="loading-content">
          <el-icon class="is-loading"><Loading /></el-icon>
          <p>正在加载题目...</p>
        </div>
      </el-card>
    </div>

    <!-- 题目内容 -->
    <div class="question-section" v-else-if="currentQuestion">
      <el-card class="question-card">
        <div class="question-header">
          <h2 class="question-number">第 {{ currentQuestionIndex + 1 }} 题</h2>
          <span class="question-dimension">{{ getDimensionName(currentQuestion.dimension) }}</span>
        </div>
        <div class="question-content">
          <p class="question-text">{{ currentQuestion.questionText }}</p>
        </div>
        <div class="options-section">
          <el-radio-group v-model="currentAnswer" @change="handleAnswerChange">
            <div class="option-item" v-for="option in currentQuestion.options" :key="option.optionId">
              <el-radio :value="option.optionId" class="option-radio">
                {{ option.optionText }}
              </el-radio>
            </div>
          </el-radio-group>
        </div>
      </el-card>
    </div>

    <!-- 导航按钮 -->
    <div class="navigation-section">
      <el-button 
        @click="previousQuestion" 
        :disabled="currentQuestionIndex === 0 || loadingCurrentQuestion"
        :loading="loadingPrevious"
      >
        <el-icon><ArrowLeft /></el-icon>
        上一题
      </el-button>
      
      <el-button 
        v-if="currentQuestionIndex < totalQuestions - 1"
        @click="nextQuestion" 
        :disabled="!currentAnswer || loadingCurrentQuestion"
        :loading="loadingNext"
        type="primary"
      >
        下一题
        <el-icon><ArrowRight /></el-icon>
      </el-button>
      
      <el-button 
        v-else
        @click="showCompleteDialog"
        :disabled="!allQuestionsAnswered"
        type="success"
      >
        <el-icon><Check /></el-icon>
        完成测试
      </el-button>
      
      <el-button 
        @click="showAbandonDialog"
        type="danger"
        plain
      >
        <el-icon><Close /></el-icon>
        放弃测试
      </el-button>
    </div>

    <!-- 题目导航 -->
    <div class="question-nav-section">
      <h3>题目导航</h3>
      <div class="question-nav-grid">
        <div 
          v-for="index in totalQuestions" 
          :key="index"
          class="nav-item"
          :class="{
            'current': index - 1 === currentQuestionIndex,
            'answered': questionIds[index - 1] && answers[questionIds[index - 1]],
            'unanswered': !questionIds[index - 1] || !answers[questionIds[index - 1]]
          }"
          @click="goToQuestion(index - 1)"
        >
          {{ index }}
        </div>
      </div>
      
    </div>

    <!-- 完成测试确认对话框 -->
    <el-dialog
      title="完成测试"
      v-model="completeDialogVisible"
      width="400px"
      :close-on-click-modal="false"
    >
      <div class="complete-dialog-content">
        <p><el-icon style="color: #E6A23C;"><Warning /></el-icon> 确认要完成测试吗？</p>
        <p>完成后将自动计算您的人格类型结果。</p>
        <div class="answer-summary">
          <p>已回答：{{ Object.keys(answers).length }} / {{ totalQuestions }} 题</p>
          <p v-if="Object.keys(answers).length < totalQuestions" style="color: #F56C6C;">
            还有 {{ totalQuestions - Object.keys(answers).length }} 题未回答
          </p>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="completeDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="completeTest" :loading="completeLoading">
            确认完成
          </el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 放弃测试确认对话框 -->
    <el-dialog
      title="放弃测试"
      v-model="abandonDialogVisible"
      width="400px"
      :close-on-click-modal="false"
    >
      <div class="abandon-dialog-content">
        <p><el-icon style="color: #F56C6C;"><Warning /></el-icon> 确认要放弃测试吗？</p>
        <p>放弃后您的答题进度将会丢失。</p>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="abandonDialogVisible = false">取消</el-button>
          <el-button type="danger" @click="abandonTestHandler" :loading="abandonLoading">
            确认放弃
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { 
  getTestQuestions,
  getQuestionDetail,
  getQuestionsDetail,
  preloadQuestions,
  submitAnswer, 
  completeTest as completeTestApi,
  getTestProgress,
  validateTestRecord
} from "@/api/mbti/test"
import { ElMessage, ElMessageBox } from 'element-plus'
import { Timer, ArrowLeft, ArrowRight, Check, Close, Warning, Loading } from '@element-plus/icons-vue'

const route = useRoute()
const router = useRouter()

// 响应式数据
const recordId = ref(null)
const testTypeId = ref(null)
const questionIds = ref([]) // 只存储题目ID列表
const questionCache = reactive(new Map()) // 题目缓存，使用Map提高性能
const currentQuestion = ref(null)
const totalQuestions = ref(0) // 总题目数
const currentQuestionIndex = ref(0)
const currentAnswer = ref(null)
const answers = reactive({}) // questionId -> optionId
const timeLimit = ref(null)
const timeRemaining = ref(0)
const timer = ref(null)
const completeDialogVisible = ref(false)
const abandonDialogVisible = ref(false)
const completeLoading = ref(false)
const abandonLoading = ref(false)
const loadingCurrentQuestion = ref(false) // 是否正在加载当前题目
const loadingNext = ref(false)
const loadingPrevious = ref(false)

const dimensionNames = {
  'E': '外向性',
  'I': '内向性', 
  'S': '感觉',
  'N': '直觉',
  'T': '思考',
  'F': '情感',
  'J': '判断',
  'P': '知觉'
}

// 计算属性
// currentQuestion 现在直接使用 ref

const progressPercentage = computed(() => {
  if (totalQuestions.value === 0) return 0
  return Math.round((Object.keys(answers).length / totalQuestions.value) * 100)
})

const allQuestionsAnswered = computed(() => {
  return Object.keys(answers).length === totalQuestions.value
})

// 生命周期
onMounted(() => {
  recordId.value = route.query.recordId
  testTypeId.value = route.query.testTypeId
  
  if (!recordId.value) {
    ElMessage.error('测试记录ID不存在')
    router.push('/mbti')
    return
  }
  
  initTest()
})

onUnmounted(() => {
  if (timer.value) {
    clearInterval(timer.value)
  }
})

// 监听器
watch(() => currentQuestionIndex.value, async (newIndex) => {
  await loadQuestion(newIndex)
  loadCurrentAnswer()
})

// 方法
const initTest = async () => {
  try {
    // 验证测试记录
    const validateResponse = await validateTestRecord(recordId.value)
    if (!validateResponse.data.valid) {
      ElMessage.error('测试记录无效或已过期')
      router.push('/mbti')
      return
    }

    // 获取测试进度
    const progressResponse = await getTestProgress(recordId.value)
    const progress = progressResponse.data
    
    // 设置时间限制
    if (progress.timeLimit) {
      timeLimit.value = progress.timeLimit * 60 // 转换为秒
      startTimer()
    }

    // 只获取题目ID列表，不获取完整题目内容
    await loadQuestionList()
    
    // 加载第一题
    await loadQuestion(0)
    
    // 预加载已有答案
    await loadExistingAnswers()
    
  } catch (error) {
    console.error('初始化测试失败:', error)
    ElMessage.error('加载测试失败')
    router.push('/mbti')
  }
}

// 只加载题目ID列表
const loadQuestionList = async () => {
  try {
    const response = await getTestQuestions(testTypeId.value, { onlyIds: true })
    const questionList = response.data || []
    
    totalQuestions.value = questionList.length
    questionIds.value = questionList.map(q => q.questionId)
    
  } catch (error) {
    console.error('加载题目列表失败:', error)
    throw error
  }
}

// 按需加载单个题目
const loadQuestion = async (index) => {
  if (index < 0 || index >= questionIds.value.length) return
  
  const questionId = questionIds.value[index]
  
  // 如果已经缓存了，直接使用
  if (questionCache.has(questionId)) {
    currentQuestion.value = questionCache.get(questionId)
    return
  }
  
  // 否则从服务器加载
  try {
    loadingCurrentQuestion.value = true
    const response = await getQuestionDetail(questionId)
    const question = response.data
    
    // 缓存题目
    questionCache.set(questionId, question)
    currentQuestion.value = question
    
    // 预加载相邻题目（提升用户体验）
    preloadAdjacentQuestions(index)
    
  } catch (error) {
    console.error('加载题目失败:', error)
    ElMessage.error('加载题目失败')
  } finally {
    loadingCurrentQuestion.value = false
  }
}

// 预加载相邻题目（后台静默加载）
const preloadAdjacentQuestions = async (currentIndex) => {
  try {
    const response = await preloadQuestions(testTypeId.value, currentIndex, 2)
    const questions = response.data || []
    
    // 缓存预加载的题目
    questions.forEach(question => {
      questionCache.set(question.questionId, question)
    })
  } catch (error) {
    // 预加载失败不影响主流程
    console.warn('预加载题目失败:', error)
  }
}


const loadExistingAnswers = async () => {
  // 从后端加载已有答案
  try {
    const response = await getTestProgress(recordId.value)
    const existingAnswers = response.data.answers || {}
    
    // 更新answers对象
    Object.assign(answers, existingAnswers)
  } catch (error) {
    console.warn('加载已有答案失败:', error)
  }
}

const startTimer = () => {
  timeRemaining.value = timeLimit.value
  timer.value = setInterval(() => {
    timeRemaining.value--
    if (timeRemaining.value <= 0) {
      timeUp()
    }
  }, 1000)
}

const timeUp = () => {
  ElMessage.warning('测试时间已到，将自动提交')
  completeTestHandler()
}

const formatTime = (seconds) => {
  const minutes = Math.floor(seconds / 60)
  const remainingSeconds = seconds % 60
  return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
}

const formatProgress = (percentage) => {
  return `${percentage}%`
}

const getDimensionName = (dimension) => {
  return dimensionNames[dimension] || dimension
}

const handleAnswerChange = (optionId) => {
  const questionId = currentQuestion.value.questionId
  answers[questionId] = optionId
  
  // 提交答案到后端
  submitCurrentAnswer()
}

const submitCurrentAnswer = async () => {
  try {
    await submitAnswer({
      recordId: recordId.value,
      questionId: currentQuestion.value.questionId,
      optionId: currentAnswer.value
    })
  } catch (error) {
    ElMessage.error('答案提交失败')
  }
}

const previousQuestion = async () => {
  if (currentQuestionIndex.value > 0) {
    loadingPrevious.value = true
    currentQuestionIndex.value--
    loadingPrevious.value = false
  }
}

const nextQuestion = async () => {
  if (currentQuestionIndex.value < totalQuestions.value - 1) {
    loadingNext.value = true
    currentQuestionIndex.value++
    loadingNext.value = false
  }
}

const goToQuestion = (index) => {
  currentQuestionIndex.value = index
}

const loadCurrentAnswer = () => {
  const questionId = currentQuestion.value?.questionId
  currentAnswer.value = answers[questionId] || null
}

const showCompleteDialog = () => {
  completeDialogVisible.value = true
}

const showAbandonDialog = () => {
  abandonDialogVisible.value = true
}

const completeTestHandler = async () => {
  // 检查是否至少回答了一些题目
  const answeredCount = Object.keys(answers).length
  if (answeredCount === 0) {
    ElMessage.warning('请至少回答一道题目后再完成测试')
    completeDialogVisible.value = false
    return
  }
  
  // 如果回答题目数量过少，给出额外提醒
  if (answeredCount < totalQuestions.value * 0.5) {
    try {
      await ElMessageBox.confirm(
        `您只回答了 ${answeredCount} / ${totalQuestions.value} 题（${Math.round(answeredCount / totalQuestions.value * 100)}%），这可能会影响测试结果的准确性。确定要完成测试吗？`,
        '回答不完整提醒',
        {
          confirmButtonText: '确定完成',
          cancelButtonText: '继续答题',
          type: 'warning',
        }
      )
    } catch {
      // 用户选择继续答题
      completeDialogVisible.value = false
      return
    }
  }
  
  completeLoading.value = true
  try {
    const response = await completeTestApi(recordId.value)
    ElMessage.success('测试完成！')
    
    // 清除计时器
    if (timer.value) {
      clearInterval(timer.value)
    }
    
    // 跳转到结果页面
    router.push({
      path: '/mbti/result',
      query: { recordId: recordId.value }
    })
  } catch (error) {
    console.error('完成测试失败:', error)
    if (error.response && error.response.data && error.response.data.msg) {
      ElMessage.error(error.response.data.msg)
    } else if (typeof error === 'string' && error.includes('未找到答题记录')) {
      ElMessage.error('请先回答一些题目再完成测试')
    } else {
      ElMessage.error('完成测试失败，请稍后重试')
    }
  } finally {
    completeLoading.value = false
    completeDialogVisible.value = false
  }
}

const abandonTestHandler = () => {
  // 清除计时器
  if (timer.value) {
    clearInterval(timer.value)
  }
  
  // 直接返回 MBTI 测试页面
  ElMessage.success('已放弃测试')
  router.push('/mbti')
  
  // 关闭对话框
  abandonLoading.value = false
  abandonDialogVisible.value = false
}

// 给模板使用的方法别名
const completeTest = completeTestHandler
const abandonTest = abandonTestHandler

// 将方法暴露给模板
defineExpose({
  completeTest: completeTestHandler,
  abandonTest: abandonTestHandler
})
</script>

<style lang="scss" scoped>
.progress-section {
  margin-bottom: 30px;
  
  .progress-info {
    display: flex;
    justify-content: space-between;
    margin-top: 10px;
    font-size: 14px;
    color: #666;
    
    .time-remaining {
      color: #E6A23C;
      font-weight: bold;
      display: flex;
      align-items: center;
      
      .el-icon {
        margin-right: 5px;
      }
    }
  }
}

.question-section {
  margin-bottom: 30px;
}

.question-card {
  .question-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
    
    .question-number {
      margin: 0;
      color: #409EFF;
    }
    
    .question-dimension {
      background: #E1F3D8;
      color: #67C23A;
      padding: 4px 12px;
      border-radius: 12px;
      font-size: 12px;
    }
  }
  
  .question-content {
    margin-bottom: 30px;
    
    .question-text {
      font-size: 18px;
      line-height: 1.6;
      color: #333;
      margin: 0;
    }
  }
  
  .options-section {
    .option-item {
      margin-bottom: 15px;
      
      .option-radio {
        width: 100%;
        
        :deep(.el-radio__label) {
          font-size: 16px;
          line-height: 1.5;
          padding-left: 10px;
        }
      }
    }
  }
}

.navigation-section {
  text-align: center;
  margin-bottom: 40px;
  
  .el-button {
    margin: 0 10px;
  }
}

.question-nav-section {
  background: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  
  h3 {
    margin-bottom: 15px;
    color: #333;
  }
  
  .question-nav-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
    gap: 10px;
    
    .nav-item {
      width: 40px;
      height: 40px;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 4px;
      cursor: pointer;
      font-weight: bold;
      transition: all 0.3s ease;
      
      &.current {
        background: #409EFF;
        color: white;
      }
      
      &.answered {
        background: #67C23A;
        color: white;
      }
      
      &.unanswered {
        background: #DCDFE6;
        color: #909399;
      }
      
      &.loading {
        background: #F4F4F5;
        color: #C0C4CC;
        position: relative;
        
        &::before {
          content: '';
          position: absolute;
          top: 50%;
          left: 50%;
          width: 12px;
          height: 12px;
          margin: -6px 0 0 -6px;
          border: 2px solid #E4E7ED;
          border-top: 2px solid #409EFF;
          border-radius: 50%;
          animation: loading-spin 1s linear infinite;
        }
      }
      
      &:hover:not(.loading) {
        transform: scale(1.1);
      }
    }
  }
  
  .loading-indicator {
    margin-top: 20px;
    padding: 15px;
    background: #fff;
    border-radius: 6px;
    border: 1px solid #e4e7ed;
    
    .progress-info {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 10px;
      font-size: 14px;
      color: #666;
      
      .loading-text {
        color: #409EFF;
        font-weight: bold;
        display: flex;
        align-items: center;
        
        .el-icon {
          margin-right: 5px;
        }
      }
    }
  }
  
  .load-complete {
    margin-top: 20px;
    padding: 15px;
    background: #f0f9ff;
    border-radius: 6px;
    border: 1px solid #67C23A;
    text-align: center;
    color: #67C23A;
    font-weight: bold;
    
    .el-icon {
      margin-right: 5px;
    }
  }
}

.complete-dialog-content,
.abandon-dialog-content {
  text-align: center;
  
  p {
    margin: 10px 0;
    font-size: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    
    .el-icon {
      margin-right: 8px;
    }
  }
  
  .answer-summary {
    background: #f5f7fa;
    padding: 15px;
    border-radius: 4px;
    margin-top: 15px;
    
    p {
      margin: 5px 0;
      font-size: 14px;
      justify-content: flex-start;
    }
  }
}

@keyframes loading-spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.loading-section {
  margin-bottom: 30px;
  
  .loading-content {
    text-align: center;
    padding: 40px;
    
    .el-icon {
      font-size: 32px;
      color: #409EFF;
      margin-bottom: 16px;
    }
    
    p {
      font-size: 16px;
      color: #666;
      margin: 0;
    }
  }
}
</style>
